﻿// Copyright (c) Appeon. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace SnapObjects.Data
{
    internal abstract class AdoDbSchemaProvider : IAdoDbSchemaProvider
    {
        protected readonly DataContext _dataContext;

        private readonly SqlColumnSchemaProvider _sqlColumnSchemaProvider;
        private readonly FunctionColumnSchemaProvider _functionColumnSchemaProvider;
        private readonly ProcedureColumnSchemaProvider _procedureColumnSchemaProvider;
        private readonly RoutineParameterSchemaProvider _functionParameterSchemaProvider;
        private readonly RoutineParameterSchemaProvider _procedureParameterSchemaProvider;

        public AdoDbSchemaProvider(DataContext dataContext)
        {
            _dataContext = dataContext;

            _sqlColumnSchemaProvider = this.CreateSqlColumnSchemaProvider();

            _procedureColumnSchemaProvider = this.CreateProcedureColumnSchemaProvider();
            _procedureParameterSchemaProvider = this.CreateProcedureParameterSchemaProvider();

            _functionColumnSchemaProvider = this.CreateFunctionColumnSchemaProvider();
            _functionParameterSchemaProvider = this.CreateFunctionParameterSchemaProvider();
        }

        public virtual IReadOnlyList<DbColumnInfo> GetSqlColumnSchema(
            string sql, IEnumerable<IAdoDbParameter> parameters)
        {
            return _sqlColumnSchemaProvider.GetColumnSchema(sql, parameters);
        }

        public virtual Task<IReadOnlyList<DbColumnInfo>> GetSqlColumnSchemaAsync(
            string sql, IEnumerable<IAdoDbParameter> parameters, CancellationToken cancellationToken)
        {
            return _sqlColumnSchemaProvider.GetColumnSchemaAsync(sql, parameters, cancellationToken);
        }

        public virtual IReadOnlyList<ProcedureSchema> GetProcedureParameterSchema(string procedure)
        {
            return _procedureParameterSchemaProvider.GetParameterSchema(procedure);
        }

        public virtual Task<IReadOnlyList<ProcedureSchema>> GetProcedureParameterSchemaAsync(
            string procedure, CancellationToken cancellationToken)
        {
            return _procedureParameterSchemaProvider.GetParameterSchemaAsync(procedure, cancellationToken);
        }

        public virtual IReadOnlyList<IReadOnlyList<DbColumnInfo>> GetProcedureColumnSchema(
            string procedure, IEnumerable<IAdoDbParameter> parameters)
        {
            return _procedureColumnSchemaProvider.GetColumnSchema(procedure, parameters);
        }

        public virtual Task<IReadOnlyList<IReadOnlyList<DbColumnInfo>>> GetProcedureColumnSchemaAsync(
          string procedure,
          IEnumerable<IAdoDbParameter> parameters,
          CancellationToken cancellationToken)
        {
            return _procedureColumnSchemaProvider.GetColumnSchemaAsync(procedure, parameters, cancellationToken);
        }

        public virtual IReadOnlyList<ProcedureSchema> GetFunctionParameterSchema(string function)
        {
            return _functionParameterSchemaProvider.GetParameterSchema(function);
        }

        public virtual Task<IReadOnlyList<ProcedureSchema>> GetFunctionParameterSchemaAsync(
            string function, CancellationToken cancellationToken)
        {
            return _functionParameterSchemaProvider.GetParameterSchemaAsync(function, cancellationToken);
        }

        public virtual IReadOnlyList<IReadOnlyList<DbColumnInfo>> GetFunctionColumnSchema(
            string function,
            FunctionReturnType functionReturnType,
            IEnumerable<IAdoDbParameter> parameters)
        {
            return _functionColumnSchemaProvider.GetColumnSchema(function, functionReturnType, parameters);
        }

        public virtual Task<IReadOnlyList<IReadOnlyList<DbColumnInfo>>> GetFunctionColumnSchemaAsync(
          string function,
          FunctionReturnType functionReturnType,
          IEnumerable<IAdoDbParameter> parameters,
          CancellationToken cancellationToken)
        {
            return _functionColumnSchemaProvider.GetColumnSchemaAsync(
                function, functionReturnType, parameters, cancellationToken);
        }

        public virtual IReadOnlyList<IAdoDbParameter> GetSqlParameterSchema(string sqlText)
        {
            return _sqlColumnSchemaProvider.GetSqlParameterSchema(sqlText);
        }

        public virtual Task<IReadOnlyList<IAdoDbParameter>> GetSqlParameterSchemaAsync(string sqlText, CancellationToken cancellationToken)
        {
            return _sqlColumnSchemaProvider.GetSqlParameterSchemaAsync(sqlText, cancellationToken);
        }

        protected abstract SqlColumnSchemaProvider CreateSqlColumnSchemaProvider();

        protected abstract ProcedureColumnSchemaProvider CreateProcedureColumnSchemaProvider();

        protected abstract RoutineParameterSchemaProvider CreateProcedureParameterSchemaProvider();

        protected abstract FunctionColumnSchemaProvider CreateFunctionColumnSchemaProvider();

        protected abstract RoutineParameterSchemaProvider CreateFunctionParameterSchemaProvider();
    }
}
